package com.ruoyi.system.coretools.apple.rest;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.codec.binary.Base64;

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 苹果三方登录RestApi流程工具类
 */
public class AppleRestApiUtil {

    private final String APPLE_DOMAIN = "https://appleid.apple.com";

    private String client_id;
    private String team_id;
    private String key_id;
    private String key_value;

    private AppleRestApiUtil(String client_id, String team_id, String key_id, String key_value) {
        this.client_id = client_id;
        this.team_id = team_id;
        this.key_id = key_id;
        this.key_value = key_value;
    }

    public static AppleRestApiUtil init(String client_id, String team_id, String key_id, String key_value) {
        return new AppleRestApiUtil(client_id, team_id, key_id, key_value);
    }

    private String getUrl(String path) {
        return APPLE_DOMAIN + path;
    }

    /**
     * 生成客户端密钥(并设置缓存时间-为了JAVA_SE都能启动去除了缓存代码)
     * 用不用缓存看个人
     * @return
     * @throws Exception
     */
    public String generateClientSecret() {
        String client_secret = null;
        try {
            client_secret = generateClientSecret(client_id, team_id, key_id, key_value);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return client_secret;
    }

    /**
     * 参考文档: https://developer.okta.com/blog/2019/06/04/what-the-heck-is-sign-in-with-apple#generate-the-client-secret
     * 生成客户端密钥
     * @param client_id 应用ID
     * @param team_id 团队ID
     * @param key_id 私钥ID
     * @param key_value 私钥内容
     * @return client_secret: 最多有效期6个月
     * @throws Exception
     */
    public String generateClientSecret(String client_id, String team_id, String key_id, String key_value) throws Exception{
        Map<String, Object> header = new HashMap<String, Object>();
        Map<String, Object> claims = new HashMap<String, Object>();
        long now = new Date().getTime() / 1000;
        header.put("kid", key_id); // 参考后台配置
        claims.put("iss", team_id); // 参考后台配置 team id
        claims.put("iat", now);
        claims.put("exp", now + 60 * 60 * 24 * 30); // 最长半年，单位秒
        claims.put("aud", APPLE_DOMAIN); // 默认值
        claims.put("sub", client_id);
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(readKey(key_value));
        KeyFactory keyFactory = KeyFactory.getInstance("EC");
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        String client_secret = Jwts.builder().setHeader(header).setClaims(claims).signWith(SignatureAlgorithm.ES256, privateKey).compact();
        return client_secret;
    }

    public  byte[] readKey(String key_value) throws Exception {
        return Base64.decodeBase64(key_value);
    }

    /**
     * 文档: https://developer.apple.com/documentation/sign_in_with_apple/revoke_tokens
     * 撤销用户token
     * url: https://appleid.apple.com/auth/revoke
     * @param accessToken 通过 refreshToken获取
     * @return
     */
    public HttpResponse revokeToken(String accessToken) {

        String url = getUrl("/auth/revoke");
        Map<String, Object> form = new HashMap<String, Object>();
        form.put("client_id", client_id);
        form.put("client_secret", generateClientSecret());
        form.put("token_type_hint","access_token");
        form.put("token", accessToken);

        HttpResponse execute = HttpRequest.post(url).header("Content-Type", "application/x-www-form-urlencoded").form(form).execute();
        return execute;
    }

    /**
     * 文档: https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens
     * 刷新用户 accessToken
     * url: https://appleid.apple.com/auth/token
     * @param refreshToken
     * @return
     */
    public HttpResponse refreshToken(String refreshToken) {

        String url = getUrl("/auth/token");
        Map<String, Object> form = new HashMap<String, Object>();
        form.put("client_id", client_id);
        form.put("client_secret", generateClientSecret());
        form.put("grant_type","refresh_token");
        form.put("refresh_token", refreshToken);

        HttpResponse execute = HttpRequest.post(url).header("Content-Type", "application/x-www-form-urlencoded").form(form).execute();
        return execute;
    }

    /**
     * 文档: https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens
     * 生成用户 accessToken
     * url: https://appleid.apple.com/auth/token
     * @param appleCode
     * @return
     */
    public HttpResponse generateToken(String appleCode) {

        String url = getUrl("/auth/token");
        Map<String, Object> form = new HashMap<String, Object>();
        form.put("client_id", client_id);
        form.put("client_secret", generateClientSecret());
        form.put("grant_type","authorization_code");
        form.put("code", appleCode);

        HttpResponse execute = HttpRequest.post(url).header("Content-Type", "application/x-www-form-urlencoded").form(form).execute();
        return execute;
    }
}
